package com.pg.ffmpeg;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.pg.ffmpeg.bean.VideoInfo;
import com.pg.ffmpeg.util.Gutil;
import com.pg.ffmpeg.util.MediaTool;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Locale;


public class TranscodeActivity extends AppCompatActivity implements View.OnClickListener {

    private final static int CODE_REQUEST_WRITE_EXTERNAL = 0x100;
    private int PICK_VIDEO_REQUEST = 0x2;
    private String mVideoPath;
    private ImageView mIvCover;
    private TextView mTvResolution;
    private TextView mTvFps;
    private TextView mTvBitrate;
    private TextView mTvDuration;
    private TextView mTvVcodec;
    private TextView mTvRotation;
    private EditText mEditTargetWidth;
    private EditText mEditTargetHeight;
    private EditText mEditTargetFPS;
    private EditText mEditTargetBitrate;
    private EditText mEditSavePath;
    private ProgressBar mPbTranscode;
    private TextView mTvTimeSpent;
    private TextView mTvProgress;
    private TextView mTvTimeRemaining;
    private VideoInfo mInfo;
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private Button mBtnStartTranscode;
    private Spinner mSpinnerPresets;
    private String mPreset;

    public static String getDetailTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());
        return sdf.format(System.currentTimeMillis());
    }

    public static String getVideoPath() {
        String path = null;
        File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
        if (!folder.exists()) {
            boolean mkdirs = folder.mkdirs();
        }
        path = folder.getAbsolutePath();
        if (!path.endsWith("/")) {
            return path + "/";
        } else {
            return path;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transcode);

        mIvCover = findViewById(R.id.iv_cover);
        mIvCover.setOnClickListener(this);
        mBtnStartTranscode = findViewById(R.id.btn_start_transcode);
        mBtnStartTranscode.setOnClickListener(this);
        mTvResolution = findViewById(R.id.tv_resolution);
        mTvFps = findViewById(R.id.tv_fps);
        mTvBitrate = findViewById(R.id.tv_bitrate);
        mTvDuration = findViewById(R.id.tv_duration);
        mTvVcodec = findViewById(R.id.tv_vcodec);
        mTvRotation = findViewById(R.id.tv_rotation);

        mEditTargetWidth = findViewById(R.id.edit_width);
        mEditTargetHeight = findViewById(R.id.edit_height);
        mEditTargetFPS = findViewById(R.id.edit_fps);
        mEditTargetBitrate = findViewById(R.id.edit_bitrate);
        mEditSavePath = findViewById(R.id.edit_save_path);
        mSpinnerPresets = findViewById(R.id.spinner_preset);
        mSpinnerPresets.setDropDownWidth(300);
        mSpinnerPresets.setDropDownHorizontalOffset(100);
        mSpinnerPresets.setDropDownVerticalOffset(100);
        final String[] presets = getResources().getStringArray(R.array.presets);
        Log.i("fred","presets is not null:"+(presets != null && presets.length >0));
        mPreset = presets[1];
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.item_selected_preset, presets);
        adapter.setDropDownViewResource(R.layout.item_presets);
        mSpinnerPresets.setAdapter(adapter);
        mSpinnerPresets.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mPreset = presets[position];
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        mSpinnerPresets.setSelection(1);

        mPbTranscode = findViewById(R.id.pb_transcode);
        mTvTimeSpent = findViewById(R.id.tv_time_spent);
        mTvProgress = findViewById(R.id.tv_trascode_progress);
        mTvTimeRemaining = findViewById(R.id.tv_time_remaining);

        checkPermission();
//        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
//            int numCodecs = MediaCodecList.getCodecCount();
//            for (int i = 0; i < numCodecs; i++) {
//                MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
//                String[] types = codecInfo.getSupportedTypes();
//                for (String type : types) {
//                    Log.i("Fred","MediaCodecList, name:"+ codecInfo.getName() + ",type:" + type);
//                }
//            }
//        }
//        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
//            MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
//            MediaCodecInfo[] infos = mediaCodecList.getCodecInfos();
//            for (MediaCodecInfo codecInfo:infos) {
//                String[] types = codecInfo.getSupportedTypes();
//                for (String type : types) {
//                    Log.i("fred","name:"+codecInfo.getName() +",type:" + type);
//                }
//            }
//        }

        a();
    }



    private void checkPermission() {
        int permissions = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permissions != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    CODE_REQUEST_WRITE_EXTERNAL
            );
        }

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.iv_cover:
                Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(i, PICK_VIDEO_REQUEST);
//                Intent localIntent = new Intent();
//                localIntent.setAction(Intent.ACTION_PICK);
//                localIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
//                startActivityForResult(localIntent, PICK_VIDEO_REQUEST);
                break;
            case R.id.btn_start_transcode:
                mIvCover.setClickable(false);
                mBtnStartTranscode.setEnabled(false);
                mTvTimeSpent.setText("耗时：00:00");
//                new Thread(new Runnable() {
//                    @Override
//                    public void run() {
//                        startTranscode();
//                startTranscode4();
                startScale();
//                startTranscode1();
//                    }
//                }).start();
                break;
        }
    }

    private void a(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
            MediaCodecInfo[] supportCodes = list.getCodecInfos();
            Log.i("fred", "解码器列表：");
            for (MediaCodecInfo codec : supportCodes) {
                if (!codec.isEncoder()) {
                    String name = codec.getName();
                    if (name.startsWith("OMX.google")) {
                        Log.i("fred", "软解->" + name);
                    }
                }
            }
            for (MediaCodecInfo codec : supportCodes) {
                if (!codec.isEncoder()) {
                    String name = codec.getName();
                    if (!name.startsWith("OMX.google")) {
                        Log.i("fred", "硬解->" + name);
                    }
                }
            }
            Log.i("fred", "编码器列表：");
            for (MediaCodecInfo codec : supportCodes) {
                if (codec.isEncoder()) {
                    String name = codec.getName();
                    if (name.startsWith("OMX.google")) {
                        Log.i("fred", "软编->" + name);
                    }
                }
            }
            for (MediaCodecInfo codec : supportCodes) {
                if (codec.isEncoder()) {
                    String name = codec.getName();
                    if (!name.startsWith("OMX.google")) {
                        Log.i("fred", "硬编->" + name);
                    }
                }
            }
        }
    }

    private void startScale() {
//        -d  打印日志
        StringBuffer buffer = new StringBuffer("ffmpeg -d -i ");
        buffer.append(mVideoPath)
                .append(" -vf transpose=1 -c:v h264 -profile:v high -c:a aac ")
                .append(getVideoPath())
                .append(getDetailTime()).append(".mp4");
        try {
            RecodeUtil.getInstance().runCommand(buffer.toString(), new RecodeCallback() {
                @Override
                public void onProgress(int progress) {
                    Log.i("fredZhu", "progress:" + progress);
                }

                @Override
                public void onComplete() {
                    Log.i("fredZhu", "onComplete");
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mIvCover.setClickable(true);
                            mBtnStartTranscode.setEnabled(true);

                        }
                    });
                }

                @Override
                public void onFail(String errorInfo) {
                    Log.i("fredZhu","onFail:"+errorInfo);
                }
            });
        }catch (Exception e){
            Log.i("fred","so库的错误");
        }

    }

    private void startTranscode4() {
//        -d  打印日志
        StringBuffer buffer = new StringBuffer("ffmpeg -d -i ");
        buffer.append(mVideoPath)
                .append(" -c:v h264 -profile:v high -c:a aac ")
                .append(getVideoPath())
                .append(getDetailTime()).append(".mp4");
        try {
            RecodeUtil.getInstance().runCommand(buffer.toString(), new RecodeCallback() {
                @Override
                public void onProgress(int progress) {
                    Log.i("fredZhu", "progress:" + progress);
                }

                @Override
                public void onComplete() {
                    Log.i("fredZhu", "onComplete");
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mIvCover.setClickable(true);
                            mBtnStartTranscode.setEnabled(true);

                        }
                    });
                }

                @Override
                public void onFail(String errorInfo) {
                    Log.i("fredZhu","onFail:"+errorInfo);
                }
            });
        }catch (Exception e){
            Log.i("fred","so库的错误");
        }

    }

    private void startTranscode3() {
//        -d  打印日志
        StringBuffer buffer = new StringBuffer("ffmpeg -d -i ");
        buffer.append("/storage/emulated/0/Movies/20200714121801.mp4")
                .append(" -i ")
                .append("/storage/emulated/0/Movies/20200714120001.aac")
                .append(" -vcodec copy -acodec copy ")
                .append(getVideoPath())
                .append(getDetailTime()).append(".avi");
        RecodeUtil.getInstance().runCommand(buffer.toString(), new RecodeCallback() {
            @Override
            public void onProgress(int progress) {
                Log.i("fredZhu","progress:"+progress);
            }

            @Override
            public void onComplete() {
                Log.i("fredZhu","onComplete");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mIvCover.setClickable(true);
                        mBtnStartTranscode.setEnabled(true);

                    }
                });
            }

            @Override
            public void onFail(String errorInfo) {
                Log.i("fredZhu","onFail:"+errorInfo);
            }
        });

    }

    //分离出音频
    private void startTranscode2() {
//        -d  打印日志
        StringBuffer buffer = new StringBuffer("ffmpeg -d -i ");
        buffer.append(mVideoPath)
                .append(" -acodec copy -vn ")
                .append(getVideoPath())
                .append(getDetailTime()).append(".aac");
        RecodeUtil.getInstance().runCommand(buffer.toString(), new RecodeCallback() {
            @Override
            public void onProgress(int progress) {
                Log.i("fredZhu","progress:"+progress);
            }

            @Override
            public void onComplete() {
                Log.i("fredZhu","onComplete");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mIvCover.setClickable(true);
                        mBtnStartTranscode.setEnabled(true);

                    }
                });
            }

            @Override
            public void onFail(String errorInfo) {
                Log.i("fredZhu","onFail:"+errorInfo);
            }
        });

    }

    /**
     * -c:v  设置视频编码器
     * -v:b  设置码率
     * -c:a  设置音频编码器
     * -f    设置文件格式（容器）
     */
    private void startTranscode1() {
//        -d  打印日志
        StringBuffer buffer = new StringBuffer("ffmpeg -d -i ");
        buffer.append(mVideoPath)
                .append(" -c:v libx264 -c:a aac ")
                .append(getVideoPath())
                .append(getDetailTime()).append(".mp4");
        try {
            RecodeUtil.getInstance().runCommand(buffer.toString(), new RecodeCallback() {
                @Override
                public void onProgress(int progress) {
                    Log.i("fredZhu", "progress:" + progress);
                }

                @Override
                public void onComplete() {
                    Log.i("fredZhu", "onComplete");
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mIvCover.setClickable(true);
                            mBtnStartTranscode.setEnabled(true);

                        }
                    });
                }

                @Override
                public void onFail(String errorInfo) {
                    Log.i("fredZhu","onFail:"+errorInfo);
                }
            });
        }catch (Exception e){
            Log.i("fred","so库的错误");
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_VIDEO_REQUEST && resultCode == RESULT_OK && null != data) {
            Uri selectedVideo = data.getData();
            getImgFilePath(selectedVideo);
            updateVideo();
        }
    }

    private void getImgFilePath(Uri param) {

        String[] filePathColumn = {MediaStore.Images.Media.DATA};
        Cursor cursor = null;
        try {
            if (param.toString().startsWith("file://")) {
                mVideoPath = param.getPath();
            } else {
                cursor = getContentResolver().query(param, filePathColumn, null, null, null);
                if (cursor != null && cursor.moveToFirst()) {
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    mVideoPath = cursor.getString(columnIndex);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                try {
                    cursor.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void updateVideo() {
//        Bitmap videoFrame = MediaTool.getVideoFrame(mVideoPath, 2000000);
//        mIvCover.setImageBitmap(videoFrame);
//        mInfo = RecodeUtil.getInstance().getVideoInfo(mVideoPath);
//        mTvResolution.setText("分辨率：" + mInfo.width + "x" + mInfo.height);
//        mTvBitrate.setText("码率：" + Gutil.bitrateFormat(mInfo.bitrate));
//        mTvFps.setText("FPS：" + mInfo.fps);
//        mTvDuration.setText("视频时长：" + Gutil.parseTime((int) mInfo.duration/1000));
//        mTvVcodec.setText("Video Codec: " + mInfo.videoCodec);
//        mTvRotation.setText("Video Rotation: " + mInfo.rotation+"°");
//
//        mEditTargetBitrate.setText("4000");
//        mEditTargetFPS.setText("30");
//        mEditTargetWidth.setText(mInfo.width + "");
//        mEditTargetHeight.setText(mInfo.height + "");
        String path = getVideoPath() + getDetailTime() + ".mp4";
        mEditSavePath.setText(path);
    }
}
